from BeautifulSoup import BeautifulSoup, NavigableString
from soupselect import select
from urllib2 import urlopen

from fontrender.converter.models import Font
from PIL import Image,ImageFont, ImageDraw
import pygame
import sys

def p_properties(pTag):
    align = hscale = vscale = None
    for attr, value in pTag.attrs:
        if attr == 'align':
            if value.lower() == 'left' or value.lower() == 'l':
                align = 'left'
            elif value.lower() == 'right' or value.lower() == 'r':
                align = 'right'
            elif value.lower() == 'center' or value.lower() == 'c':
                align = 'center'
            elif value.lower() == 'justify' or value.lower() == 'j':
                align = 'justify'
            elif value.lower() == 'ljustify' or value.lower() == 'lj':
                align = 'ljustify'
            elif value.lower() == 'rjustify' or value.lower() == 'rj':
                align = 'rjustify'
            elif value.lower() == 'cjustify' or value.lower() == 'cj':
                align = 'cjustify'                
        elif attr == 'width':
            hscale = value
        elif attr == 'height':
            vscale = value
    return (align,hscale,vscale)

def p_content(pTag):
    for p in pTag.contents:
        bold = italic = underline = False
        q = p
        while type(q) is not NavigableString:
            if q.name == u'i': italic = True
            elif q.name == u'b': bold = True
            elif q.name == u'u': underline = True            
            q = q.next
        text = q.string
        print text

def htmlparse(data):
    doc = BeautifulSoup(data)
    for c in doc.contents:
        if type(c) is NavigableString:
            print c
        elif c.name == u'p':
            prop = p_properties(c)
            p_content(c)
    
    return select(doc, 'p')

class FontRenderer(pygame.font.Font):
    def __init__(self,font,data, *args, **kwargs):
        self.letter_spacing = float(data['letter_spacing'])
        self.color = self.color_to_rgb(data['color'])
        self.data = data
        
        xxx = htmlparse(data['message'])

        pygame.font.init()
        super(FontRenderer,self).__init__(font.font_file.path, int(data['size']),*args,**kwargs)
        if data['leading'] == 'auto':
            self.leading = self.get_height()
        else:
            self.leading = int(data['leading'])        
        self.set_bold(data['bold'])
        self.set_italic(data['italic'])
        self.set_underline(data['underline'])

    def color_to_rgb(self,colorstring):
        r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:]
        r, g, b = [int(n, 16) for n in (r, g, b)]
        return (r, g, b)

    def get_letter_spacing(self, text):
        delta = self.size(text)[0] - (self.size(text[0])[0] + self.size(text[1])[0])
        return int(self.letter_spacing * self.size(" ")[0] + delta)

    def get_leading(self):
        return int(self.get_height() * self.leading)

    def line_width(self,text):
        length = self.size(text[0])[0]
        return length + reduce(lambda res, x: res + self.get_letter_spacing(text[x:x+2]) + self.size(text[x+1])[0],
                               range(0,len(text)-1), 0)

    def line_size(self,text):
        return (self.line_width(text), self.get_height())

    def get_size(self):
        parts = self.data['message'].split("\n")
        height = (len(parts)-1) * self.leading + self.get_height()
        width = reduce(lambda res, x: max([res,self.line_width(x)]), parts, self.line_width(parts[0]))
        
        return (width,height)

    def draw_line(self, text):
        if len(text) == 0:
            return pygame.Surface((1,1),pygame.SRCALPHA,32)

        offset = 0
        surf = pygame.Surface((self.img_size[0],self.get_height()),pygame.SRCALPHA,32)
        if self.data['alignment'] == 'left':
            h = 0
        elif self.data['alignment'] == 'right':
            h = self.img_size[0] - self.line_size(text)[0]
        elif self.data['alignment'] == 'center':
            h = (self.img_size[0] - self.line_size(text)[0])/2
        elif self.data['alignment'] == 'justified':
            h = 0
            offset = int((self.img_size[0] - self.line_size(text)[0])/(len(text)-1))

        char = self.render(text[0], True, self.color)
        surf.blit(char,(h, 0))
        h += self.size(text[0])[0]

        for i in range(0,len(text)-1):
            h += self.get_letter_spacing(text[i:i+2]) + offset
            char = self.render(text[i+1], True, self.color)
            surf.blit(char,(h, 0))
            h += self.size(text[i+1])[0]

        return surf

    def image(self):
        self.img_size = self.get_size()

        surf = pygame.Surface(self.img_size,pygame.SRCALPHA,32)

        h = 0
        for item in self.data['message'].split("\n"):
            surf.blit(self.draw_line(item.replace('\r','')), (0, h))
            h += self.leading

        hscale = float(self.data['horizontal_scale'])/100
        vscale = float(self.data['vertical_scale'])/100
        pil_image = Image.fromstring("RGBA",self.img_size,pygame.image.tostring(surf,'RGBA'))
        if hscale!=1 or vscale!=1:
            tu = (0,0, self.img_size[0]-1, self.img_size[1] - 1)
            pil_image = pil_image.transform((self.img_size[0]*hscale, self.img_size[1]*vscale), Image.EXTENT,  tu, Image.BICUBIC)            

        return pil_image
